/**
 * Cube.Component is the absolute base of a Cube component. It is able to listen for events and render itself.
 * 
 * @class Cube.Component
 * @mixin Cube.util.Observable
 */
Cube.define("Cube.Component", {
	implements: 'Cube.util.Observable',
	
	/**
	 * The component itself
	 * 
	 * @property {HTMLElement} 
	 */
	element: null,
	
	/**
	 * Element's classes
	 * 
	 * @property {Array} 
	 */
	classes: [],
	
	/**
	 * Constructor 
	 */
	constructor: function() {
		this.element = new Cube.Element(document.createElement('div'));

		this.setMinWidth(this.minWidth);
		this.setMinHeight(this.minHeight);
		this.setWidth(this.width);
		this.setHeight(this.height);
		this.setDraggable(this.draggable);
		
		this.setupElementEvents();
	},
	
	/**
	 * Add class to component
	 * 
	 * If you want, you can add multiple classes at once, by adding them as arguments.
	 * 
	 * 	component.addClass('class1', 'class2', 'class3');
	 * 
	 * @param {String} classname
	 */
	addClass: function(className) {
		this.element.addClass.apply(this.element, arguments);
	},
	
	/**
	 * Remove a class from a component
	 * 
	 * @param {String} className 
	 */
	removeClass: function(className) {
		this.element.removeClass.apply(this.element, arguments);
	},
	
	/**
	 * Shows and renders the component on the screen. 
	 */
	show: function() {
		this.render();
	},
	
	/**
	 * Render component to any element you want. By default, the component will be rendered to the document body.
	 * 
	 * @param {String/HTMLElement} (optional) Element to append this component
	 */
	render: function(element) {
		if (!element)
		{
			document.body.appendChild(this.element.dom);
		}
		else if (element instanceof Cube.Element)
		{
			element.dom.appendChild(this.element.dom);
		}
		else
		{
			element.appendChild(this.element.dom);
		}
	},
	
	/**
	 * 
	 */
	css: function(item, value) {
		var style = this.element.getStyle();
		var css = (style) ? Cube.String.trim(Cube.String.trim(style), ';') + ';' : '';

		this.element.setStyle(css + item + ': ' + value);
	},
	
	setMinWidth: function(minWidth) {
		this.element.setMinWidth(minWidth);
	},
	
	setMinHeight: function(minHeight) {
		this.element.setMinHeight(minHeight);
	},
	
	setWidth: function(width) {
		this.element.setWidth(width);
	},
	
	setHeight: function(height) {
		this.element.setHeight(height);
	},
	
	setHtml: function(html) {
		this.element.setHtml(html);
	},
	
	setDraggable: function(draggable) {		
		if (typeof(draggable) === "object")
		{
			var defaults = {
				delegate: this
			};
			
			var draggable = this.parseConfig(draggable, defaults);

			if (draggable.delegate instanceof Cube.Component)
			{
				draggable.delegate = draggable.delegate.element;
			}
			else if (draggable.delegate instanceof HTMLElement)
			{
				draggable.delegate = new Cube.Element(draggable.delegate);
			}
			
			// Make sure the element is absolute
			this.element.setPosition('absolute');
			
			draggable.delegate.setCursor('move');
			
			var clientX = 0, clientY = 0, offsetX = 0, offsetY = 0;
			var body = new Cube.Element(document.body);
			
			draggable.delegate.on({
				mousedown: function(e) {
					if (e.preventDefault) e.preventDefault();
					
					clientX = e.clientX, clientY = e.clientY;
					
					offsetX = this.element.getLeft();
					offsetY = this.element.getTop();
										
					body.addListener('mousemove', function(e) {
						var diffX = (e.clientX - clientX) + offsetX;
						var diffY = (e.clientY - clientY) + offsetY;
											
						this.element.setLeft(diffX);
						this.element.setTop(diffY);
					}, this);
					
					return false;
				}
			}, this);
			
			body.addListener('mouseup', function() {
				body.removeListener('mousemove');
			});
		}
	},
	
	setupElementEvents: function() {
		var el = new Cube.Element(this.element);
	}
});